/*
 * pps_bom
 */
package com.pitop.bom.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baidu.fsg.uid.UidGenerator;
import com.pitop.assembly.dao.AssemblyDAO;
import com.pitop.assembly.entity.Assembly;
import com.pitop.assembly.entity.AssemblyState;
import com.pitop.bom.dao.BomDAO;
import com.pitop.bom.dao.BomDetailDAO;
import com.pitop.bom.dao.BomDetailLogDAO;
import com.pitop.bom.entity.*;
import com.pitop.bom.vo.BomDetailVO;
import com.pitop.core.base.BaseDAO;
import com.pitop.core.base.BaseSVImpl;
import com.pitop.core.entity.Page;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.exceptions.BomDetailException;
import com.pitop.core.exceptions.BomException;
import com.pitop.core.tools.StringTools;
import com.pitop.material.dao.MaterialDAO;
import com.pitop.material.entity.Material;
import com.pitop.material.entity.MaterialState;
import com.pitop.supplier.dao.SupplierDAO;
import com.pitop.supplier.entity.Supplier;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("bomDetailSV")
@Slf4j
public class BomDetailSVImpl extends BaseSVImpl<BomDetail, Long> implements BomDetailSV {

    @Autowired
    private BomDetailDAO bomDetailDAO;

    @Autowired
    private AssemblyDAO assemblyDAO;

    @Autowired
    private MaterialDAO materialDAO;
    @Autowired
    private BomDetailLogDAO bomDetailLogDAO;
    @Autowired
    private BomDAO bomDAO;
    @Autowired
    private SupplierDAO supplierDAO;

    @Resource
    private UidGenerator uidGenerator;

    @Override
    protected BaseDAO getBaseDAO() {
        return bomDetailDAO;
    }

    /**
     * 保存account对象
     *
     * @param entity 实体
     * @throws BaseException
     */
    @Override
    public void save(BomDetail entity) throws BaseException {
        entity.setCode(String.valueOf(uidGenerator.getUID()));
        super.save(entity);
    }

    /**
     * 加载一个对象BomDetail
     *
     * @param id
     * @param code 编码
     * @return BomDetail
     */
    @Override
    public BomDetail load(Long id, String code) {
        if (id == null && code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDetailDAO.load(param);
    }

    /**
     * 加载一个对象BomDetail,(将查询关联数据)
     *
     * @param id
     * @param code 编码
     * @return BomDetail
     */
    @Override
    public BomDetail get(Long id, String code) {
        if (id == null && code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDetailDAO.getDetail(id, code);
    }

    /**
     * 加载一个对象BomDetail 通过id
     *
     * @param id
     * @return BomDetail
     */
    @Override
    public BomDetail loadById(Long id) {
        if (id == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDetailDAO.loadById(id);
    }

    /**
     * 加载一个对象BomDetail 通过code
     *
     * @param code 编码
     * @return BomDetail
     */
    @Override
    public BomDetail loadByCode(String code) {
        if (code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDetailDAO.loadByCode(code);
    }

    /**
     * 加载一个对象BomDetail 通过id,(将查询关联数据)
     *
     * @param id
     * @return BomDetail
     */
    @Override
    public BomDetail getById(Long id) {
        if (id == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return bomDetailDAO.getById(id);
    }

    /**
     * 加载一个对象BomDetail 通过code,(将查询关联数据)
     *
     * @param code 编码
     * @return BomDetail
     */
    @Override
    public BomDetail getByCode(String code) {
        if (code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        BomDetail bomDetail = bomDetailDAO.getByCode(code);
        if(bomDetail != null && StringTools.isNotEmpty(bomDetail.getSupplierCode())) {
            Supplier supplier = supplierDAO.loadByCode(bomDetail.getSupplierCode());
            bomDetail.setSupplierName(supplier.getName());
        }
        return bomDetail;
    }

    /**
     * 根据主键id,oldStates 共同更新 BomDetail 的状态到newState状态
     *
     * @param id
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateById(Long id, BomDetailState newState, BomDetailState... oldStates) {
        if (id == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        bomDetailDAO.updateStateById(id, new Date(), newState.name(), states);
    }

    /**
     * 根据主键code,oldStates 共同更新 BomDetail 的状态到newState状态
     *
     * @param code      编码
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateByCode(String code, BomDetailState newState, BomDetailState... oldStates) {
        if (code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        bomDetailDAO.updateStateByCode(code, new Date(), newState.name(), states);
    }

    /**
     * 根据主键id 更新 BomDetail 的状态到另一个状态
     *
     * @param id
     * @param state 状态
     */
    @Override
    public void updateById(Long id, BomDetailState state) {
        if (id == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        bomDetailDAO.updateById(id, state.name(), new Date());
    }

    /**
     * 根据主键code 更新 BomDetail 的状态到另一个状态
     *
     * @param code  编码
     * @param state 状态
     */
    @Override
    public void updateByCode(String code, BomDetailState state) {
        if (code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        bomDetailDAO.updateByCode(code, state.name(), new Date());
    }


    /**
     * 删除对象BomDetail
     *
     * @param id * @param code 编码
     * @return BomDetail
     */
    @Override
    public void delete(Long id, String code) {
        if (id == null && code == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        bomDetailDAO.delete(param);
    }


    /**
     * 查询BomDetail分页
     *
     * @param bomDetail 对象
     * @param offset    查询开始行
     * @param limit     查询行数
     * @return List<BomDetail>
     */
    @Override
    public List<BomDetail> list(BomDetail bomDetail, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map = null;
        if (bomDetail != null) {
            map = JSON.parseObject(JSON.toJSONString(bomDetail, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        List<BomDetail> bomDetailList = bomDetailDAO.list(map, new RowBounds(offset, limit));
        if(bomDetailList.size() > 0) {
            for (BomDetail bomDetailFlag : bomDetailList) {
                if(StringTools.isNotEmpty(bomDetailFlag.getSupplierCode())) {
                    bomDetailFlag.setSupplierName(supplierDAO.loadByCode(bomDetailFlag.getSupplierCode()).getName());
                }
            }
        }
        return bomDetailList;
    }

    @Override
    public int count(BomDetail bomDetail) {
        Map<String, Object> map = null;
        if (bomDetail != null) {
            map = JSON.parseObject(JSON.toJSONString(bomDetail, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return bomDetailDAO.count(map);
    }

    /**
     * 查询BomDetail分页
     *
     * @param id     * @param code  编码
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<BomDetail>
     */
    @Override
    public List<BomDetail> list(Long id, String code, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDetailDAO.list(param, new RowBounds(offset, limit));
    }

    @Override
    public int count(Long id, String code) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        return bomDetailDAO.count(param);
    }

    /**
     * 添加bom明细
     * 1.参数合法性验证
     * 2.该bom下是否已经保存了该bom明细
     * 3.物料是否是可用状态，组件是否是稳定状态
     * 4.如果是物料，查询出物料供应商，如果没有供应商，说明是模具物料
     * 5.保存bom明细
     * 6.添加日志信息
     * @param bomDetail     bom明细
     * @param account       管理员账户
     * @param code          管理员账户编码
     */
    @Override
    public void save(BomDetail bomDetail, String account, String code) {
        //1.参数合法性验证
        if(bomDetail == null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        //2.该bom下是否已经保存了该bom明细
        Map<String, Object> params = new HashedMap();
        params.put("bomCode",bomDetail.getBomCode());
        params.put("materialAssemblyCode", bomDetail.getMaterialAssemblyCode());
        BomDetail bomDetailFlag = bomDetailDAO.load(params);
        if(bomDetailFlag != null) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Exists);
        }
        //3.物料是否是可用状态，组件是否是稳定状态
        if(BomDetailType.Assembly == BomDetailType.getEnum(bomDetail.getType())) {
            Assembly assembly = assemblyDAO.loadByCode(bomDetail.getMaterialAssemblyCode());
            if(assembly == null) {
                throw new BomDetailException(BaseException.BaseExceptionEnum.Result_Not_Exist);
            }
            if(AssemblyState.Stable != AssemblyState.getEnum(assembly.getState())) {
                throw new BomDetailException(BaseException.BaseExceptionEnum.State_Is_Not_Stable);
            }
        } else {
            Material material = materialDAO.loadByCode(bomDetail.getMaterialAssemblyCode());
            if(material == null) {
                throw new BomDetailException(BaseException.BaseExceptionEnum.Result_Not_Exist);
            }
            if(MaterialState.Enable != MaterialState.getEnum(material.getState())) {
                throw new BomDetailException(BaseException.BaseExceptionEnum.Material_Is_Not_Enable);
            }
            bomDetail.setSupplierCode(material.getMaterialSupplier().getSuppierCode());
        }
        //5.保存bom明细
        bomDetail.setCode(String.valueOf(uidGenerator.getUID()));
        bomDetail.setState(BomDetailState.Develop.name());
        super.save(bomDetail);

        //6.保存日志信息
        BomDetailLog bomDetailLog = new BomDetailLog();
        bomDetailLog.setBomDetailCode(bomDetail.getCode());
        bomDetailLog.setEvent(BomDetailLogState.Create.name());
        bomDetailLog.setOperateCode(code);
        bomDetailLog.setOperateName(account);
        bomDetailLog.setSummary(bomDetail.getSummary());
        bomDetailLog.setCreateTime(new Date());
        bomDetailLogDAO.insert(bomDetailLog);
    }

    /**
     * 添加bom明细
     *
     * @param bomDetailVOs bom明细
     * @param account      管理员账户
     * @param code         管理员账户编码
     */
    @Override
    public void save(List<BomDetailVO> bomDetailVOs, String account, String code) {
        //1.参数合法性验证
        if(bomDetailVOs.size() <= 0) {
            throw new BomDetailException(BaseException.BaseExceptionEnum.Empty_Param);
        }
        Map<String, Object> params = new HashedMap();
        BomDetail bomDetailFlag;
        for (BomDetailVO bomDetailVO : bomDetailVOs) {
            params.put("bomCode",bomDetailVO.getBomCode());
            params.put("materialAssemblyCode", bomDetailVO.getMaterialAssemblyCode());
            bomDetailFlag = bomDetailDAO.load(params);
            if(bomDetailFlag != null) {
                continue;
            }
            //3.物料是否是可用状态，组件是否是稳定状态
            if(BomDetailType.Assembly == BomDetailType.getEnum(bomDetailVO.getType())) {
                Assembly assembly = assemblyDAO.loadByCode(bomDetailVO.getMaterialAssemblyCode());
                if(assembly == null || AssemblyState.Stop == AssemblyState.getEnum(assembly.getState())) {
                    continue;
                }

            } else {
                Material material = materialDAO.loadByCode(bomDetailVO.getMaterialAssemblyCode());
                if(material == null || MaterialState.Enable != MaterialState.getEnum(material.getState())) {
                    continue;
                }
            }
            BomDetail bomDetail = StringTools.convertObject(bomDetailVO, BomDetail.class);
            //5.保存bom明细
            bomDetail.setCode(String.valueOf(uidGenerator.getUID()));
            bomDetail.setState(BomDetailState.Develop.name());
            super.save(bomDetail);

            //6.保存日志信息
            String summery = "管理员" + account +",创建了bom明细：" + bomDetail.getName();
            BomDetailLog bomDetailLog = new BomDetailLog();
            bomDetailLog.setBomDetailCode(bomDetail.getCode());
            bomDetailLog.setEvent(BomDetailLogState.Create.name());
            bomDetailLog.setOperateCode(code);
            bomDetailLog.setOperateName(account);
            bomDetailLog.setSummary(summery);
            bomDetailLog.setCreateTime(new Date());
            bomDetailLogDAO.insert(bomDetailLog);
        }

    }

    /**
     * 修改bom明细
     * 1.修改bom
     * 2.添加日志信息
     * @param bomDetail     bom明细
     * @param account       管理员账户
     * @param code          管理员账户编码
     */
    @Override
    public void modify(BomDetail bomDetail, String account, String code) {
        super.modify(bomDetail);
        //2..添加日志信息
        String summery = "管理员" + account +",修改了bom明细：" + bomDetail.getName();
        BomDetailLog bomDetailLog = new BomDetailLog();
        bomDetailLog.setBomDetailCode(bomDetail.getCode());
        bomDetailLog.setEvent(BomDetailLogState.Modify.name());
        bomDetailLog.setOperateCode(code);
        bomDetailLog.setOperateName(account);
        bomDetailLog.setSummary(summery);
        bomDetailLog.setCreateTime(new Date());
        bomDetailLogDAO.insert(bomDetailLog);

    }

    /**
     * 修改bom明细状态
     *
     * @param code  组件编码
     * @param state 状态
     */
    @Override
    public void updateState(String code, String state) {
        BomDetail bomDetail = bomDetailDAO.loadByCode(code);
        if(bomDetail == null) {
            throw new BomException(BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        bomDetail.setState(state);
        bomDetailDAO.update(bomDetail);
    }

}
